﻿using BaseFramework;
using LiteFramework.Contract;
using LiteFramework.Model;
using LiteFramework.Server.Component;
using System;

namespace LiteFramework.Server
{
    public interface IUserScope : IDisposable
    {
        User OriginalUser { get; }
        string OriginalPrimeTag { get; }
    }

    [Serializable]
    public class UserScope : IUserScope
    {
        private FlowUser _flowContext = null;
        private string _token = null;

        public UserScope(User user, string primeTag)
        {
            if (user.IsOnline)
                throw new AccessSecurityException();

            _flowContext = new FlowUser();

            LogonComponent comp = (LogonComponent)ServerApplication.ComponentFactory.Create<ILogonContract>();
            _token = comp.GetSecurityToken(user.UserName, primeTag);

            if (!String.IsNullOrEmpty(_token))
            {
                var newUser = ServerApplication.ComponentFactory.Create<UserComponent>().Get(user.ID);
                user.InternalBag.SetValue("IsOnline", true);

                if (ServerApplication.Context != null)
                    ServerApplication.Context.User = user;
                if (ServerApplication.ApplicationContext != null)
                    ServerApplication.ApplicationContext.User = user;
            }
        }

        public User OriginalUser
        {
            get { return _flowContext.OriginalUser; }
        }

        public string OriginalPrimeTag
        {
            get { return _flowContext.OriginalPrimeTag; }
        }

        public void Dispose()
        {
            try
            {
                LogonComponent comp = (LogonComponent)ServerApplication.ComponentFactory.Create<ILogonContract>();
                comp.Logout(_token);
            }
            finally
            {
                if (ServerApplication.Context != null)
                    ServerApplication.Context.User = null;
                if (ServerApplication.ApplicationContext != null)
                    ServerApplication.ApplicationContext.User = null;

                if (_flowContext != null)
                    _flowContext.Dispose();
            }
        }
    }

    [Serializable]
    public class ApproleScope : IUserScope
    {
        private FlowUser _flowContext = null;

        public ApproleScope()
            : this(null)
        {
        }

        public ApproleScope(string primeTag)
        {
            _flowContext = new FlowUser();

            ServerApplication.Current.SetApproleUnderstudy(this);

            if (primeTag != null)
                ServerApplication.Current.InitPrimeTag(primeTag);
        }

        public User OriginalUser
        {
            get { return _flowContext.OriginalUser; }
        }

        public string OriginalPrimeTag
        {
            get { return _flowContext.OriginalPrimeTag; }
        }

        public void Dispose()
        {
            if (_flowContext != null)
                _flowContext.Dispose();

            ServerApplication.Current.SetApproleUnderstudy(null);
        }
    }

    [Serializable]
    public class AdminScope : IUserScope
    {
        private FlowUser _flowContext = null;

        public AdminScope()
            : this(null)
        {
        }

        public AdminScope(string primeTag)
        {
            _flowContext = new FlowUser();

            ServerApplication.Current.SetAdminUnderstudy(this);

            if (primeTag != null)
                ServerApplication.Current.InitPrimeTag(primeTag);
        }

        public User OriginalUser
        {
            get { return _flowContext.OriginalUser; }
        }

        public string OriginalPrimeTag
        {
            get { return _flowContext.OriginalPrimeTag; }
        }

        public void Dispose()
        {
            if (_flowContext != null)
                _flowContext.Dispose();

            ServerApplication.Current.SetAdminUnderstudy(null);
        }
    }
}
